package org.demo.mine.model;

import lombok.extern.log4j.Log4j2;
import org.demo.mine.util.IKeyible;
import org.demo.mine.util.ListHashMap;

import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author:LiaoYouLe
 * @Date: Created in 2018/8/31
 * @Description
 * @Modifyied By:
 */
@Log4j2
public class Box implements IKeyible<Integer> {
    private int id;
    private Set<Box> groundBoxs;
    private boolean hasUnBoxed = false;
    private boolean isMine;


    public static Box getInstance(int id, boolean isMine) {
        return new Box(id, isMine);
    }

    private Box(int id, boolean isMine) {
        this.groundBoxs = new HashSet<Box>(8);
        this.id = id;
        this.isMine = isMine;
    }

    public int getId() {
        return id;
    }

    public boolean isMine() {
        return isMine;
    }

    public void setMine(boolean mine) {
        isMine = mine;
    }

    public void addGroundBox(Box box) {
        this.groundBoxs.add(box);
    }

    public boolean hasUnBoxed() {
        return hasUnBoxed;
    }


    public void unBoxed() {
        this.hasUnBoxed = true;
    }


    public Long getGroundMineNum() {
        return this.groundBoxs
                .stream()
                .filter(Box::isMine)
                .collect(Collectors.counting());
    }

    public Set<Box> getGroundBoxs() {
        return groundBoxs;
    }


    public void unBoxing(ListHashMap<Integer, Box> boxes) {
        if (hasUnBoxed) {
            return;
        }
        if (isMine) {
            log.info("box {} is mine", id);
            boxes.forEach(Box::unBoxed);
            return;
        }
        this.hasUnBoxed = true;
        if (0 == getGroundMineNum()) {
            unBoxingGround(getGroundBoxs());
        }
    }


    public void unBoxingGround(Set<Box> groundBoxs) {
        for (Box groundBox : groundBoxs) {
            if (!groundBox.isMine() && !groundBox.hasUnBoxed()) {
                groundBox.unBoxed();
                if (0 == groundBox.getGroundMineNum()) {
                    unBoxingGround(groundBox.getGroundBoxs());
                }
            }
        }
    }

    @Override
    public Integer Key() {
        return this.id;
    }
}
